import React from "react";
import {
  Table,
  Space,
  Button,
  Modal,
  Form,
  Input,
  message,
  Select,
} from "antd";
import type { ColumnsType, TablePaginationConfig } from "antd/es/table";
import type { FilterValue, SorterResult } from "antd/es/table/interface";
import { ColumnType, FilterConfirmProps } from "antd/lib/table/interface";
import { SearchOutlined } from "@ant-design/icons";
import Highlighter from "react-highlight-words";
import { useRequest } from "ahooks";

import { ResourceI, RoleI, TenantI } from "../../types/system";
import {
  createRole,
  getRoleDetail,
  searchResourceList,
  searchRoleList,
  searchTenantList,
  updateRole,
} from "../../api/system";
import styles from "./index.module.less";
import { dayjs } from "../../App";
import { useLocation, useNavigate } from "react-router-dom";
import { CustomResponse } from "../../api/http_class";

const RoleManage = (): JSX.Element => {
  const location = useLocation();
  const navigate = useNavigate();
  const [showEditModal, setShowEditModal] = React.useState<boolean>(false);
  const [submitting, setSubmitting] = React.useState<boolean>(false);
  const [formDisabled] = React.useState<boolean>(false);
  const [searchText, setSearchText] = React.useState("");
  // const [searchedColumn, setSearchedColumn] = React.useState("");
  // const [loadingRoleList, setLoadingRoleList] = React.useState<boolean>(false);
  const [roleCount, setRoleCount] = React.useState<number>(0);
  const [tenantList, setTenantList] = React.useState<TenantI[]>([]);
  const [roleList, setRoleList] = React.useState<RoleI[]>([]);
  const [selectedRowKeys, setSelectedRowKeys] = React.useState<React.Key[]>([]);
  const [selectedRows, setSelectedRows] = React.useState<ResourceI[]>([]);
  const [resourceList, setResourceList] = React.useState<ResourceI[]>([]);
  const [filteredResourceList, setFilteredResourceList] = React.useState<
    ResourceI[]
  >([]);
  const searchInput = React.useRef<any>(null);
  const [roleForm] = Form.useForm<RoleI>();
  // const [importForm] = Form.useForm();

  const { loading, run } = useRequest(
    (paramsString: string) => searchRoleList(paramsString),
    {
      manual: false,
      defaultParams: [location.search.replace(/^\?/, "")],
      onSuccess(resp, params) {
        // console.log(params);
        console.log(resp.data.data);
        setRoleList(resp.data.data);
        setRoleCount(resp.data.totalCount);
      },
      onError(e, params) {
        message.error("获取数据失败");
      },
    }
  );

  useRequest((paramsString: string) => searchTenantList(paramsString), {
    manual: false,
    defaultParams: [""],
    onSuccess(resp, params) {
      console.log(params);
      setTenantList(resp.data.data);
    },
    onError(e, params) {
      message.error("获取数据失败");
    },
  });

  const { loading: loadingResourceList } = useRequest(
    (paramsString: string) => searchResourceList(paramsString),
    {
      manual: false,
      defaultParams: [location.search.replace(/^\?/, "")],
      onSuccess(resp, params) {
        console.log(params);
        setResourceList(resp.data.data);
        setFilteredResourceList(resp.data.data);
      },
      onError(e, params) {
        message.error("获取数据失败");
      },
    }
  );

  // 表头下拉搜索
  type DataIndex = keyof RoleI;
  const handleSearch = (
    selectedKeys: string[],
    confirm: (param?: FilterConfirmProps) => void,
    dataIndex: DataIndex
  ) => {
    try {
      setSearchText(selectedKeys[0]);
      // setSearchedColumn(String(dataIndex));
      // confirm触发TableChange动作
      confirm();
    } catch (err) {
      // Uncaught TypeError: Cannot set properties of null (setting 'checked')
      console.log(err);
    }
  };

  const handleReset = (clearFilters: () => void) => {
    // clearFilters();
    try {
      clearFilters();
    } catch (err) {
      // Uncaught TypeError: Cannot set properties of null (setting 'checked')
      console.log(err);
    }
  };

  const getColumnSearchProps: any = (
    dataIndex: DataIndex
  ): ColumnType<typeof columns> => ({
    filterDropdown: ({
      setSelectedKeys,
      selectedKeys,
      confirm,
      clearFilters,
    }) => (
      <div style={{ padding: 8 }} onKeyDown={(e) => e.stopPropagation()}>
        <Input
          ref={searchInput}
          placeholder={`Search ${dataIndex}`}
          value={selectedKeys[0] as any}
          onChange={(e) =>
            setSelectedKeys(e.target.value ? [e.target.value] : [])
          }
          onPressEnter={() =>
            handleSearch(selectedKeys as string[], confirm, dataIndex)
          }
          style={{ marginBottom: 8, display: "block" }}
        />
        <Space>
          <Button
            type="primary"
            onClick={() =>
              handleSearch(selectedKeys as string[], confirm, dataIndex)
            }
            icon={<SearchOutlined />}
            size="small"
            style={{ width: 90 }}
          >
            搜索
          </Button>
          <Button
            onClick={() => clearFilters && handleReset(clearFilters)}
            size="small"
            style={{ width: 90 }}
          >
            重置
          </Button>
          <Button
            type="link"
            size="small"
            onClick={() => {
              confirm({ closeDropdown: false });
              setSearchText((selectedKeys as string[])[0]);
              // setSearchedColumn(dataIndex);
            }}
          >
            筛选
          </Button>
          <Button
            type="link"
            size="small"
            onClick={() => {
              // close();
              console.log("close()");
            }}
          >
            关闭
          </Button>
        </Space>
      </div>
    ),
    filterIcon: (filtered: boolean) => (
      <SearchOutlined style={{ color: filtered ? "#1890ff" : undefined }} />
    ),
    onFilter: (value, record: any) => {
      // 后端过滤好了，前端全部展示即可。
      // console.log(record);
      // console.log(record[dataIndex.toString().split(".")[0]]);
      return true;
    },
    // onFilterDropdownOpenChange: (visible: any) => {
    // 	if (visible) {
    // 		setTimeout(() => searchInput.current?.select(), 100);
    // 	}
    // },
    onFilterDropdownOpenChange: (visible: any) => {
      if (visible) {
        setTimeout(() => searchInput.current?.select(), 100);
      }
    },
    // render: (value: any, record: ColumnsType<RoleI>, index: number): React.ReactNode => {
    render: (value: any, record: any, index: number): React.ReactNode => {
      // console.log(value);
      // console.log(record);
      // console.log(searchedColumn);
      // console.log(dataIndex);
      // console.log(dataIndex.toString().split(".")[0]);
      // console.log(dataIndex.toString().split(".")[1]);
      // console.log(record[index]);
      // console.log(record[dataIndex.toString().split(".")[0]]);
      // console.log(record[dataIndex.toString().split(".")[0]][dataIndex.toString().split(".")[1]]);
      // console.log(typeof record[dataIndex.toString().split(".")[0]]);
      if (typeof record[dataIndex.toString().split(".")[0]] === "object") {
        // console.log(record[dataIndex.toString().split(".")[0]]);
        if (record[dataIndex.toString().split(".")[0]]) {
          // console.log(
          // 	record && record[dataIndex.toString().split(".")[0]] && record[dataIndex.toString().split(".")[0]][dataIndex.toString().split(".")[1]]
          // 		? record[dataIndex.toString().split(".")[0]][dataIndex.toString().split(".")[1]].toString()
          // 		: ""
          // );
          return (
            <Highlighter
              highlightStyle={{ backgroundColor: "#ffc069", padding: 0 }}
              searchWords={[searchText]}
              autoEscape
              textToHighlight={
                record &&
                record[dataIndex.toString().split(".")[0]] &&
                record[dataIndex.toString().split(".")[0]][
                  dataIndex.toString().split(".")[1]
                ]
                  ? record[dataIndex.toString().split(".")[0]][
                      dataIndex.toString().split(".")[1]
                    ].toString()
                  : ""
              }
            />
          );
        } else {
          return <span></span>;
        }
      } else {
        return (
          <Highlighter
            highlightStyle={{ backgroundColor: "#ffc069", padding: 0 }}
            searchWords={[searchText]}
            autoEscape
            textToHighlight={
              record && record[dataIndex.toString().split(".")[0]]
                ? record[dataIndex.toString().split(".")[0]].toString()
                : ""
            }
          />
        );
      }
    },
  });

  const columns: ColumnsType<RoleI> = [
    {
      title: "所在中心",
      dataIndex: "tenant.name",
      width: "200px",
      ellipsis: true,
      key: "tenant.name",
      sorter: (a: RoleI, b: RoleI) => {
        if (a.tenant && b.tenant) {
          return a.tenant.name.localeCompare(b.tenant.name);
        } else {
          return 0;
        }
      },
      ...getColumnSearchProps("tenant.name"),
    },
    {
      title: "角色名称",
      dataIndex: "name",
      width: "200px",
      ellipsis: true,
      key: "name",
      sorter: (a: RoleI, b: RoleI) => {
        return a.name.localeCompare(b.name);
      },
      render: (text) => <span>{text}</span>,
      ...getColumnSearchProps("name"),
    },
    {
      title: "创建时间",
      dataIndex: "createdAt",
      width: "200px",
      ellipsis: true,
      key: "createdAt",
      sorter: (a: RoleI, b: RoleI) => {
        return dayjs(a.createdAt).valueOf() - dayjs(b.createdAt).valueOf();
      },
      render: (text) => {
        return <span>{dayjs(text).format("YYYY-MM-DD HH:mm:ss")}</span>;
      },
    },
    {
      title: "操作",
      dataIndex: "operation",
      width: "200px",
      ellipsis: true,
      fixed: "right" as const,
      key: "operation",
      render: (_: any, record: RoleI) => (
        <Space>
          <Button onClick={handleEditRoleClick.bind(this, record)} size="small">
            编辑
          </Button>
          {/* <Popconfirm
            title="删除此项"
            okText="删除"
            cancelText="取消"
            onConfirm={handleDeleteRoleClick.bind(this, record)}
          >
            <Button size="small" danger>
              删除
            </Button>
          </Popconfirm> */}
        </Space>
      ),
    },
  ];

  const resourceColumns: ColumnsType<ResourceI> = [
    {
      title: "权限简介",
      dataIndex: "summary",
      width: "200px",
      ellipsis: true,
      key: "summary",
      sorter: (a: ResourceI, b: ResourceI) => {
        if (a.summary && b.summary) {
          return a.summary.localeCompare(b.summary);
        } else {
          return 0;
        }
      },
      render: (value: string, record: ResourceI) => (
        <span>{value || record.name}</span>
      ),
    },
    {
      title: "描述",
      dataIndex: "description",
      width: "200px",
      ellipsis: true,
      key: "description",
      render: (value: string) => {
        return <span>{value}</span>;
      },
    },
  ];

  // 权限列表选择
  const rowSelection = {
    selectedRowKeys,
    onChange: (
      newSelectedRowKeys: React.Key[],
      newSelectedRows: ResourceI[]
    ) => {
      setSelectedRows(newSelectedRows);
      setSelectedRowKeys(newSelectedRowKeys);
    },
  };

  // 权限搜索
  const handleKeywordChange = (event: any) => {
    console.log(event.target.value);
    const tmp = resourceList.filter((item: ResourceI) => {
      return (
        (item &&
          item.name &&
          item.name.toLowerCase().indexOf(event.target.value.toLowerCase()) >=
            0) ||
        (item &&
          item.summary &&
          item.summary
            .toLowerCase()
            .indexOf(event.target.value.toLowerCase()) >= 0) ||
        (item &&
          item.description &&
          item.description
            .toLowerCase()
            .indexOf(event.target.value.toLowerCase()) >= 0)
      );
    });
    setFilteredResourceList(tmp);
  };

  const handleEditRoleClick = (record: RoleI) => {
    console.log(record);
    getRoleDetail(record.id).then(
      (res: CustomResponse<RoleI>) => {
        console.log(res.data);
        // console.log(user);
        // 设置权限表格的选中项
        const tmpKeys = res.data.resources.map((item: ResourceI) => {
          return item.name;
        });
        setSelectedRowKeys(tmpKeys);
        const tmpRows = res.data.resources.map((item: ResourceI) => {
          return item;
        });
        setSelectedRows(tmpRows);
        roleForm.setFieldsValue(res.data);
      },
      (err: any) => {
        message.error(err.detail);
      }
    );
    setShowEditModal(true);
  };

  const handleAddClick = () => {
    roleForm.resetFields();
    setShowEditModal(true);
  };

  const handleEditModalOk = () => {
    roleForm
      .validateFields()
      .then((values: any) => {
        console.log(values);
        values.resources = selectedRows;
        setSubmitting(true);
        if (values.id) {
          updateRole(values).then(
            (res) => {
              // console.log(res);
              roleForm.resetFields();
              setSubmitting(false);
              setShowEditModal(false);
              run(location.search.replace(/^\?/, ""));
            },
            (err: any) => {
              console.log(err);
              message.error(err.detail);
              setSubmitting(false);
              setShowEditModal(false);
            }
          );
        } else {
          createRole(values).then(
            (res) => {
              // console.log(res);
              roleForm.resetFields();
              setSubmitting(false);
              setShowEditModal(false);
              run(location.search.replace(/^\?/, ""));
            },
            (err: any) => {
              console.log(err);
              message.error(err.detail);
              setSubmitting(false);
              setShowEditModal(false);
            }
          );
        }
      })
      .catch((err) => {
        console.error(err);
      });
  };

  const handleEditModalCancel = () => {
    setShowEditModal(false);
  };

  // 表格条件改变时，将表格参数写到URL并根据表格条件重新获取数据
  const handleTableChange = (
    newPagination: TablePaginationConfig,
    newFilters: Record<string, FilterValue | null>,
    newSorters: SorterResult<RoleI> | SorterResult<RoleI>[]
  ) => {
    const params = new URLSearchParams();
    params.set("currentPage", newPagination.current?.toString() || "1");
    params.set("pageSize", newPagination.pageSize?.toString() || "10");

    params.set("filters", JSON.stringify(newFilters));
    params.set("sorters", JSON.stringify(newSorters));

    // console.log(`${location.pathname}${params.toString()}`);
    // console.log(`${params.toString()}`);
    navigate(`${location.pathname}?${params.toString()}`);
    // refreshRoleList(params.toString());
    run(params.toString());
  };

  // const refreshRoleList = React.useCallback((paramsString: string) => {
  // 	setLoadingRoleList(true);
  // 	searchRoleList(paramsString).then(
  // 		(res: any) => {
  // 			console.log(res);
  // 			setRoleList(res.data.data);
  // 			setLoadingRoleList(false);
  // 		},
  // 		(err: any) => {
  // 			console.log(err);
  // 			message.error(err.detail);
  // 			setLoadingRoleList(false);
  // 		}
  // 	);
  // }, []);

  const handleResourceTableChange = (
    newPagination: TablePaginationConfig,
    newFilters: Record<string, FilterValue | null>,
    newSorters: SorterResult<ResourceI> | SorterResult<ResourceI>[]
  ) => {
    const tmp = resourceList;
    tmp.sort((a: ResourceI, b: ResourceI) => {
      if (Array.isArray(newSorters)) {
        console.log("没必须组合排序");
        return 0;
      } else {
        if (newSorters.order === "descend") {
          return a.name.localeCompare(b.name);
        } else {
          return -a.name.localeCompare(b.name);
        }
      }
    });
    setFilteredResourceList(tmp);
  };

  // const refreshTenantList = React.useCallback((paramsString: string) => {
  // 	searchTenantList(paramsString).then(
  // 		(res: any) => {
  // 			// console.log(res);
  // 			setTenantList(res.data.data);
  // 		},
  // 		(err: any) => {
  // 			console.log(err);
  // 		}
  // 	);
  // }, []);

  // const refreshResourceList = React.useCallback((paramsString: string) => {
  // 	searchResourceList(paramsString).then(
  // 		(res: any) => {
  // 			console.log(res);
  // 			setResourceList(res.data.data);
  // 			setFilteredResourceList(res.data.data);
  // 		},
  // 		(err: any) => {
  // 			// console.log(err);
  // 			message.error(err.detail);
  // 		}
  // 	);
  // }, []);

  // React.useEffect(() => {
  // 	// console.log(location);
  // 	// 获取URL中的参数
  // 	// const urlSearchParams = new URLSearchParams(location.search);
  // 	// console.log(urlSearchParams);
  // 	refreshTenantList("");
  // 	refreshResourceList("");
  // 	// console.log(location.search);
  // 	// refreshRoleList(location.search.replace(/^\?/, ""));
  // }, [location, refreshRoleList, refreshTenantList, refreshResourceList]);

  return (
    <div className={styles.table}>
      <div>
        <div className={styles.tableHeader}>
          <Space style={{ marginBottom: 16 }}>
            <Button onClick={handleAddClick} size="small">
              添加
            </Button>
          </Space>
        </div>
        <Table
          columns={columns}
          rowKey={(record: RoleI) => record.id}
          dataSource={roleList}
          // expandable={{
          // 	defaultExpandedRowKeys: ["0"]
          // }}
          pagination={{
            total: roleCount,
          }}
          loading={loading}
          onChange={handleTableChange}
          scroll={{ x: 800, y: 600 }}
        ></Table>
      </div>
      <Modal
        title={roleForm.getFieldValue("id") ? "修改角色" : "添加角色"}
        open={showEditModal}
        onOk={handleEditModalOk}
        onCancel={handleEditModalCancel}
        confirmLoading={submitting}
      >
        <Form
          form={roleForm}
          layout="vertical"
          name={"roleForm"}
          autoComplete="off"
          disabled={formDisabled}
        >
          <Form.Item
            name="id"
            label="id"
            hidden={!roleForm.getFieldValue("id")}
            hasFeedback
            rules={[
              {
                required: false,
                message: "请输入id",
              },
            ]}
          >
            <Input disabled={true} />
          </Form.Item>
          <Form.Item
            label="所属中心"
            name="tenantId"
            rules={[{ required: true, message: "请选择所在中心" }]}
            hasFeedback
          >
            <Select
              showSearch
              style={{ width: "100%" }}
              filterOption={(input, option) => {
                return (
                  (option?.py ?? "").toString().toLowerCase().includes(input) ||
                  (option?.pinyin ?? "")
                    .toString()
                    .toLowerCase()
                    .includes(input) ||
                  (option?.children ?? "")
                    .toString()
                    .toLowerCase()
                    .includes(input)
                );
              }}
            >
              {tenantList.map((item: TenantI) => {
                return (
                  <Select.Option value={item.id} key={item.id}>
                    {item.name}
                  </Select.Option>
                );
              })}
            </Select>
          </Form.Item>
          <Form.Item
            name="name"
            label="角色名称"
            hasFeedback
            rules={[
              {
                required: true,
                message: "请输入角色名称",
              },
              {
                min: 2,
                message: "角色名称至少2位",
              },
              {
                max: 32,
                message: "角色名称至多32位",
              },
            ]}
          >
            <Input />
          </Form.Item>
        </Form>
        <Space>
          <Form.Item label="查找权限">
            <Input placeholder="关键词" onChange={handleKeywordChange} />
          </Form.Item>
        </Space>
        <Table
          rowSelection={rowSelection}
          loading={loadingResourceList}
          columns={resourceColumns}
          rowKey={(record: ResourceI) => record.name}
          dataSource={filteredResourceList}
          onChange={handleResourceTableChange}
        ></Table>
      </Modal>
    </div>
  );
};

export default RoleManage;
